//
// Created by immor on 2025/4/6.
//

#include "LinuxTwoWire.h"
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>

LinuxI2C::LinuxI2C(const char *device)
{
    _fd = open(device, O_RDWR);
    if (_fd < 0) {
        perror("Failed to open I2C device");
        exit(1);
    }
}

LinuxI2C::~LinuxI2C()
{
    close(_fd);
    _fd = -1;
}

void LinuxI2C::beginTransmission(uint8_t addr) const
{
    if (ioctl(_fd, I2C_SLAVE, addr) < 0) {
        perror("Failed to set I2C address");
        exit(1);
    }
}


size_t LinuxI2C::write(const uint8_t data)
{
    if (_bufferEndIndex >= I2C_MAX_BUFFER_SIZE) {
        std::cerr << "I2C buffer overflow" << std::endl;
        exit(1);
    }
    _buffer[_bufferEndIndex++] = data;
    return 1;
}

uint8_t LinuxI2C::endTransmission()
{
    if (::write(_fd, &_buffer, _bufferEndIndex) != _bufferEndIndex) {
        perror("I2C write failed");
        return 1;
    }
    _bufferEndIndex = 0;
    return 0;
}

uint8_t LinuxI2C::requestFrom(uint8_t addr, uint8_t len)
{
    if (ioctl(_fd, I2C_SLAVE, addr) < 0) {
        perror("Failed to set I2C address");
        exit(1);
    }
    return len;
}

uint8_t LinuxI2C::read()
{
    uint8_t buf;
    if (::read(_fd, &buf, 1) != 1) {
        perror("I2C read failed");
        exit(1);
    }
    return buf;
}
